//
//  MKUIWaterFlowLayoutConstraint.m
//  MKUI
//
//  Created by 苏尚进 on 2023/2/17.
//  Copyright © 2023 moon. All rights reserved.
//

#import "MKUIWaterFlowLayoutConstraint.h"
#import "MKUILayoutConstraintItemAttribute.h"

@interface MKUIWaterFlowLayoutConstraint ()
@property(nonatomic,strong) MKUILayoutConstraintItemAttributeSection *itemAttributeSection;
@end

@implementation MKUIWaterFlowLayoutConstraint
- (MKCGAxis)layoutDirectionAxis{
    MKCGAxis X = self.layoutDirection==MKUILayoutConstraintDirectionHorizontal?MKCGAxisX:MKCGAxisY;
    return X;
}
- (CGSize)itemSizeForItem:(id<MKUILayoutConstraintItemProtocol>)item thatFits:(CGSize)size resizeItems:(BOOL)resizeItems{
    if(size.width<=0||size.height<=0){
        return CGSizeZero;
    }
    CGSize itemSize = CGSizeZero;
    CGSize limitSize = size;
    if(resizeItems){
        if([item respondsToSelector:@selector(sizeThatFits:resizeItems:)]){
            itemSize = [item sizeThatFits:limitSize resizeItems:resizeItems];
        }else if([item respondsToSelector:@selector(sizeThatFits:)]){
            itemSize = [item sizeThatFits:limitSize];
        }else{
            itemSize = [item sizeOfLayout];
        }
    }else{
        itemSize = [item sizeOfLayout];
    }
    return itemSize;
}

- (CGSize)sizeThatFits:(CGSize)size{
    CGSize sizeFits = [self sizeThatFits:size resizeItems:NO];
    return sizeFits;
}
- (nullable MKUILayoutConstraintItemAttributeSection *)itemAttributeSectionThatFits:(CGSize)size resizeItems:(BOOL)resizeItems{
    NSArray *items = self.layoutedItems;
    NSInteger count = items.count;
    if(count==0) return nil;
    MKUILayoutConstraintItemAttributeSection *allLines = [[MKUILayoutConstraintItemAttributeSection alloc] init];
    
    MKCGAxis X = [self layoutDirectionAxis];
    MKCGAxis Y = MKCGAxisReverse(X);
    
    UIEdgeInsets contentInsets = self.contentInsets;
    
    CGFloat xSpacing = X==MKCGAxisX?self.interitemSpacing:self.lineSpacing;
    CGFloat ySpacing = X==MKCGAxisX?self.lineSpacing:self.interitemSpacing;
    
    CGSize originLimitSize = CGSizeMake(size.width-contentInsets.left-contentInsets.right, size.height-contentInsets.top-contentInsets.bottom);//限制在 size -contentInsets 矩形内
    CGFloat originLimitWidth = MKCGSizeGetLength(originLimitSize, X);
    CGFloat originLimitHeight = MKCGSizeGetLength(originLimitSize, Y);
    
    //超出上限的元素，都放在第maxLines行（有效行是[0,maxLines-1]）
    NSInteger maxLines =  self.maxLines;
    CGSize lastLineItemSize = CGSizeZero;
    BOOL hadLastLineItem = NO;
    if(self.lastLineItem!=nil){
        hadLastLineItem = YES;
        lastLineItemSize = [self itemSizeForItem:self.lastLineItem thatFits:originLimitSize resizeItems:resizeItems];
    }
    MKUILayoutConstraintItemAttributeSection *overLine = [[MKUILayoutConstraintItemAttributeSection alloc] init];//存放超出的行
    
    CGSize limitSize = originLimitSize;
    //以下类命名，以水平流动时为基准
    
    CGRect f1 = CGRectZero;
    MKUILayoutConstraintItemAttributeSection *line = [[MKUILayoutConstraintItemAttributeSection alloc] init];
    NSInteger effectCountAtOneLine = 0;
    NSInteger lineIndex = 0;
    for(int i=0;i<items.count;i++){
        BOOL isLast = i==items.count-1;
        id<MKUILayoutConstraintItemProtocol> item = items[i];
        
        if(maxLines>0 && lineIndex>=maxLines){//元素都添加到超出行
            MKUILayoutConstraintItemAttribute *itemAttr = [[MKUILayoutConstraintItemAttribute alloc] initWithItem:item];
            itemAttr.size = CGSizeZero;
            [overLine addItemAttribute:itemAttr];
            continue;
        }
        
        CGFloat limitWidth = MKCGSizeGetLength(limitSize, X);
        
        CGSize itemSize = [self itemSizeForItem:item thatFits:limitSize resizeItems:resizeItems];
        CGFloat h = MKCGSizeGetLength(itemSize, Y);
        CGFloat w = MKCGSizeGetLength(itemSize, X);
        
        if(w>limitWidth && effectCountAtOneLine>0){//当前行剩余空间不足以容纳item，且非第一个有效元素时，换行
            line.size = [line sizeThatFlowLayoutItemsWithSpacing:xSpacing axis:X];
            CGFloat maxRowHeight = MKCGRectGetLength(line.layoutFrame, Y);
            [allLines addItemAttribute:line];
            lineIndex++;
            
            if(maxLines>0 && lineIndex>=maxLines){//超出行数限制,指针回退，将元素都添加到overLine
                i--;
                continue;
            }
            
            line = [[MKUILayoutConstraintItemAttributeSection alloc] init];
            effectCountAtOneLine = 0;
            MKCGRectAddMin(&f1, Y, maxRowHeight+ySpacing);
            MKCGRectSetMin(&f1, X, 0);
            MKCGSizeSetLength(&limitSize, X, originLimitWidth);
            MKCGSizeSetLength(&limitSize, Y, originLimitHeight-MKCGRectGetMin(f1, Y));
            
            //指针回退，重新再算一次
            i--;
            continue;
        }
        
        f1.size = itemSize;
        if(w>limitWidth){//限制元素不能超出容器
            MKCGRectAddLength(&f1, X, -(w-limitWidth));
        }
        
        if(w>0 && h>0){
            MKCGRectSetMin(&f1, X, MKCGRectGetMax(f1, X)+xSpacing);
            limitWidth = MAX(0,limitWidth-w-xSpacing);
            effectCountAtOneLine++;
        }
        
        MKUILayoutConstraintItemAttribute *itemAttr = [[MKUILayoutConstraintItemAttribute alloc] initWithItem:item];
        itemAttr.size = f1.size;
        [line addItemAttribute:itemAttr];
        
        if(limitWidth<=0||isLast){//容器剩余尺寸为0时换行，或者到最后一个元素
            line.size = [line sizeThatFlowLayoutItemsWithSpacing:xSpacing axis:X];
            CGFloat maxRowHeight = MKCGRectGetLength(line.layoutFrame, Y);
            [allLines addItemAttribute:line];
            lineIndex++;
            
            if(maxLines>0 && lineIndex>=maxLines){//超出行数限制将后续元素都添加到overLine
                continue;
            }
            
            line = [[MKUILayoutConstraintItemAttributeSection alloc] init];
            effectCountAtOneLine = 0;
            MKCGRectAddMin(&f1, Y, maxRowHeight+ySpacing);
            MKCGRectSetMin(&f1, X, 0);
            MKCGSizeSetLength(&limitSize, X, originLimitWidth);
            MKCGSizeSetLength(&limitSize, Y, originLimitHeight-MKCGRectGetMin(f1, Y));
        }else{
            MKCGSizeSetLength(&limitSize, X, limitWidth);
        }
    }
    
    MKUILayoutConstraintItemAttributeSection *lastLine = allLines.itemAttributs.lastObject;
    if(lastLine && hadLastLineItem){
        BOOL needAddLastItem = maxLines>0 && ( overLine.itemAttributs.count>0 || self.showLastLineItemWithinMaxLine);
        
        if(needAddLastItem){
            MKUILayoutConstraintItemAttribute *lastLineItemAttr = [[MKUILayoutConstraintItemAttribute alloc] initWithItem:self.lastLineItem];
            lastLineItemAttr.size = lastLineItemSize;
            //将lastItem添加到最后一行，同时最后一行元素的布局，并没有扣掉lastItem的尺寸，因此整个最后一行都要重新布局
            NSArray<id<MKUILayoutConstraintItemAttributeProtocol> > *itemAttributs = lastLine.itemAttributs;
            CGSize limitSize = lastLine.layoutFrame.size;
            CGFloat lastLineItemWidth = MKCGSizeGetLength(lastLineItemSize, X);
            for(NSInteger i=itemAttributs.count-1;i>=0;i--){
                MKUILayoutConstraintItemAttribute *itemAttr = itemAttributs[i];
                CGSize itemSize = itemAttr.size;
                if(CGSizeEqualToSize(itemSize, CGSizeZero)){//空尺寸跳过
                    continue;
                }
                CGFloat limitWidth = MKCGSizeGetLength(itemSize, X)+MKCGSizeGetLength(originLimitSize, X)-MKCGSizeGetLength(limitSize, X)-xSpacing-lastLineItemWidth;//容器尺寸扣除掉lastItem尺寸
                MKCGSizeSetLength(&limitSize, X,limitWidth);
                if(MKCGSizeGetLength(itemSize, X)>limitWidth){
                    //扣除掉lastItem尺寸之后，剩余空间不足以容纳itemSize，需要重新计算itemSize
                    itemSize = [self itemSizeForItem:(id<MKUILayoutConstraintItemProtocol>)itemAttr.item thatFits:limitSize resizeItems:resizeItems];
                }
                CGFloat w = MKCGSizeGetLength(itemSize, X);
                if(w>limitWidth){
                    if(maxLines>0 && allLines.itemAttributs.count>=maxLines){//设置为不显示
                        itemAttr.size = CGSizeZero;//移入overLine中
                        [lastLine removeItemAttributeAtIndex:i];
                        [overLine insertItemAttribute:itemAttr atIndex:0];
                        continue;
                    }else{
                        //另起一行放lastLineItem
                        MKUILayoutConstraintItemAttributeSection *newLine = [[MKUILayoutConstraintItemAttributeSection alloc] init];
                        [newLine addItemAttribute:lastLineItemAttr];
                        newLine.size = [newLine sizeThatFlowLayoutItemsWithSpacing:xSpacing axis:X];
                        [allLines addItemAttribute:newLine];
                        break;
                    }
                }else{
                    itemAttr.size = itemSize;
                }
                [lastLine addItemAttribute:lastLineItemAttr];
                lastLine.size = [lastLine sizeThatFlowLayoutItemsWithSpacing:xSpacing axis:X];
                break;
            }
        }
        
        if(overLine.itemAttributs.count>0){
            [allLines addItemAttribute:overLine];
        }
    }
    
    allLines.size = [allLines sizeThatFlowLayoutItemsWithSpacing:ySpacing axis:Y];
    return allLines;
}
- (BOOL)overMaxLines{
    BOOL overMaxLines = self.maxLines>0 && self.itemAttributeSection.itemAttributs.count>self.maxLines;
    return overMaxLines;
}
- (CGSize)sizeThatFits:(CGSize)size resizeItems:(BOOL)resizeItems{
    CGSize sizeFits = CGSizeZero;
    UIEdgeInsets contentInsets = self.contentInsets;
    MKUILayoutConstraintItemAttributeSection *allLines = [self itemAttributeSectionThatFits:size resizeItems:resizeItems];
    sizeFits = allLines.layoutFrame.size;
    if(sizeFits.width>0&&sizeFits.height>0){
        sizeFits.width += contentInsets.left+contentInsets.right;
        sizeFits.height += contentInsets.top+contentInsets.bottom;
    }
    return sizeFits;
}
- (void)layoutItems{
    [self layoutItemsWithResizeItems:NO];
}
- (void)layoutItemsWithResizeItems:(BOOL)resizeItems{
    CGSize size = self.bounds.size;
    BOOL needRevert = (self.layoutDirection==MKUILayoutConstraintDirectionHorizontal&&self.layoutHorizontalAlignment==MKUILayoutConstraintHorizontalAlignmentRight)
    ||(self.layoutDirection==MKUILayoutConstraintDirectionVertical&&self.layoutVerticalAlignment==MKUILayoutConstraintVerticalAlignmentBottom)
    ;
    
    MKUILayoutConstraintItemAttributeSection *allLines = [self itemAttributeSectionThatFits:size resizeItems:resizeItems];
    MKCGAxis X = [self layoutDirectionAxis];
    MKCGAxis Y = MKCGAxisReverse(X);
    
    UIEdgeInsets contentInsets = self.contentInsets;
    
    CGFloat xSpacing = X==MKCGAxisX?self.interitemSpacing:self.lineSpacing;
    CGFloat ySpacing = X==MKCGAxisX?self.lineSpacing:self.interitemSpacing;
    
    MKCGRectAlignment alignX = self.layoutDirection==MKUILayoutConstraintDirectionVertical?MKCGRectAlignmentFromMKUILayoutConstraintVerticalAlignment(self.layoutVerticalAlignment):MKCGRectAlignmentFromMKUILayoutConstraintHorizontalAlignment(self.layoutHorizontalAlignment);
    MKCGRectAlignment alignY = self.layoutDirection==MKUILayoutConstraintDirectionHorizontal?MKCGRectAlignmentFromMKUILayoutConstraintVerticalAlignment(self.layoutVerticalAlignment):MKCGRectAlignmentFromMKUILayoutConstraintHorizontalAlignment(self.layoutHorizontalAlignment);
    
    CGRect bounds = UIEdgeInsetsInsetRect(self.bounds, contentInsets);
    CGRect f1 = allLines.layoutFrame;
    MKCGRectAlignToRect(&f1, Y, alignY, bounds);
    MKCGRectAlignToRect(&f1, X, alignX, bounds);
    allLines.layoutFrame = f1;
    
    BOOL applyLastItemFrame = NO;
    [allLines flowLayoutItemsWithSpacing:ySpacing axis:Y alignment:alignX needRevert:NO];
    for(MKUILayoutConstraintItemAttributeSection *line in allLines.itemAttributs){
        [line flowLayoutItemsWithSpacing:xSpacing axis:X alignment:alignY needRevert:needRevert];
        for(MKUILayoutConstraintItemAttribute *itemAttr in line.itemAttributs){
            [itemAttr applyAttributeWithResizeItems:resizeItems];
            if(itemAttr.item==self.lastLineItem){
                applyLastItemFrame = YES;
            }
        }
    }
    if(self.lastLineItem && !applyLastItemFrame){
        CGRect f1 = self.lastLineItem.layoutFrame;
        f1.size = CGSizeZero;
        self.lastLineItem.layoutFrame = f1;
    }
    self.itemAttributeSection = allLines;
}
@end

MKDEF_EnumTypeCategories(MKUIWaterFlowLayoutConstraintParam,
(@{
   @(MKUIWaterFlowLayoutConstraintParam_H_C_C):@"H_C_C",
   @(MKUIWaterFlowLayoutConstraintParam_H_C_L):@"H_C_L",
   @(MKUIWaterFlowLayoutConstraintParam_H_C_R):@"H_C_R",
   @(MKUIWaterFlowLayoutConstraintParam_H_T_C):@"H_T_C",
   @(MKUIWaterFlowLayoutConstraintParam_H_T_L):@"H_T_L",
   @(MKUIWaterFlowLayoutConstraintParam_H_T_R):@"H_T_R",
   @(MKUIWaterFlowLayoutConstraintParam_H_B_L):@"H_B_L",
   @(MKUIWaterFlowLayoutConstraintParam_H_B_C):@"H_B_C",
   @(MKUIWaterFlowLayoutConstraintParam_H_B_R):@"H_B_R",
   @(MKUIWaterFlowLayoutConstraintParam_V_C_C):@"V_C_C",
   @(MKUIWaterFlowLayoutConstraintParam_V_C_L):@"V_C_L",
   @(MKUIWaterFlowLayoutConstraintParam_V_C_R):@"V_C_R",
   @(MKUIWaterFlowLayoutConstraintParam_V_T_C):@"V_T_C",
   @(MKUIWaterFlowLayoutConstraintParam_V_T_L):@"V_T_L",
   @(MKUIWaterFlowLayoutConstraintParam_V_T_R):@"V_T_R",
   @(MKUIWaterFlowLayoutConstraintParam_V_B_C):@"V_B_C",
   @(MKUIWaterFlowLayoutConstraintParam_V_B_L):@"V_B_L",
   @(MKUIWaterFlowLayoutConstraintParam_V_B_R):@"V_B_R",
   }))

@implementation MKUIWaterFlowLayoutConstraint(InitMethod)
//////////////////////////////////////////////////////////////////////////////
+ (NSDictionary<NSNumber *,NSArray<NSNumber *> *> *)ConstraintParamMap{
    static NSDictionary<NSNumber *,NSArray<NSNumber *> *> * __share__;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSMutableDictionary<NSNumber *,NSArray<NSNumber *> *> *map = [[NSMutableDictionary alloc] init];
        map[@(MKUIWaterFlowLayoutConstraintParam_H_C_C)] = @[
          @(MKUILayoutConstraintDirectionHorizontal),
          @(MKUILayoutConstraintVerticalAlignmentCenter),
          @(MKUILayoutConstraintHorizontalAlignmentCenter),
          ];
        map[@(MKUIWaterFlowLayoutConstraintParam_H_C_L)] = @[
          @(MKUILayoutConstraintDirectionHorizontal),
          @(MKUILayoutConstraintVerticalAlignmentCenter),
          @(MKUILayoutConstraintHorizontalAlignmentLeft),
          ];
        map[@(MKUIWaterFlowLayoutConstraintParam_H_C_R)] = @[
          @(MKUILayoutConstraintDirectionHorizontal),
          @(MKUILayoutConstraintVerticalAlignmentCenter),
          @(MKUILayoutConstraintHorizontalAlignmentRight),
          ];
        map[@(MKUIWaterFlowLayoutConstraintParam_H_T_C)] = @[
          @(MKUILayoutConstraintDirectionHorizontal),
          @(MKUILayoutConstraintVerticalAlignmentTop),
          @(MKUILayoutConstraintHorizontalAlignmentCenter),
          ];
        map[@(MKUIWaterFlowLayoutConstraintParam_H_T_L)] = @[
          @(MKUILayoutConstraintDirectionHorizontal),
          @(MKUILayoutConstraintVerticalAlignmentTop),
          @(MKUILayoutConstraintHorizontalAlignmentLeft),
          ];
        map[@(MKUIWaterFlowLayoutConstraintParam_H_T_R)] = @[
          @(MKUILayoutConstraintDirectionHorizontal),
          @(MKUILayoutConstraintVerticalAlignmentTop),
          @(MKUILayoutConstraintHorizontalAlignmentRight),
          ];
        map[@(MKUIWaterFlowLayoutConstraintParam_H_B_L)] = @[
          @(MKUILayoutConstraintDirectionHorizontal),
          @(MKUILayoutConstraintVerticalAlignmentBottom),
          @(MKUILayoutConstraintHorizontalAlignmentLeft),
          ];
        map[@(MKUIWaterFlowLayoutConstraintParam_H_B_C)] = @[
          @(MKUILayoutConstraintDirectionHorizontal),
          @(MKUILayoutConstraintVerticalAlignmentBottom),
          @(MKUILayoutConstraintHorizontalAlignmentCenter),
          ];
        map[@(MKUIWaterFlowLayoutConstraintParam_H_B_R)] = @[
          @(MKUILayoutConstraintDirectionHorizontal),
          @(MKUILayoutConstraintVerticalAlignmentBottom),
          @(MKUILayoutConstraintHorizontalAlignmentRight),
          ];
        map[@(MKUIWaterFlowLayoutConstraintParam_V_C_C)] = @[
          @(MKUILayoutConstraintDirectionVertical),
          @(MKUILayoutConstraintVerticalAlignmentCenter),
          @(MKUILayoutConstraintHorizontalAlignmentCenter),
          ];
        map[@(MKUIWaterFlowLayoutConstraintParam_V_C_L)] = @[
          @(MKUILayoutConstraintDirectionVertical),
          @(MKUILayoutConstraintVerticalAlignmentCenter),
          @(MKUILayoutConstraintHorizontalAlignmentLeft),
          ];
        map[@(MKUIWaterFlowLayoutConstraintParam_V_C_R)] = @[
          @(MKUILayoutConstraintDirectionVertical),
          @(MKUILayoutConstraintVerticalAlignmentCenter),
          @(MKUILayoutConstraintHorizontalAlignmentRight),
          ];
        map[@(MKUIWaterFlowLayoutConstraintParam_V_T_C)] = @[
          @(MKUILayoutConstraintDirectionVertical),
          @(MKUILayoutConstraintVerticalAlignmentTop),
          @(MKUILayoutConstraintHorizontalAlignmentCenter),
          ];
        map[@(MKUIWaterFlowLayoutConstraintParam_V_T_L)] = @[
          @(MKUILayoutConstraintDirectionVertical),
          @(MKUILayoutConstraintVerticalAlignmentTop),
          @(MKUILayoutConstraintHorizontalAlignmentLeft),
          ];
        map[@(MKUIWaterFlowLayoutConstraintParam_V_T_R)] = @[
          @(MKUILayoutConstraintDirectionVertical),
          @(MKUILayoutConstraintVerticalAlignmentTop),
          @(MKUILayoutConstraintHorizontalAlignmentRight),
          ];
        map[@(MKUIWaterFlowLayoutConstraintParam_V_B_C)] = @[
          @(MKUILayoutConstraintDirectionVertical),
          @(MKUILayoutConstraintVerticalAlignmentBottom),
          @(MKUILayoutConstraintHorizontalAlignmentCenter),
          ];
        map[@(MKUIWaterFlowLayoutConstraintParam_V_B_L)] = @[
          @(MKUILayoutConstraintDirectionVertical),
          @(MKUILayoutConstraintVerticalAlignmentBottom),
          @(MKUILayoutConstraintHorizontalAlignmentLeft),
          ];
        map[@(MKUIWaterFlowLayoutConstraintParam_V_B_R)] = @[
          @(MKUILayoutConstraintDirectionVertical),
          @(MKUILayoutConstraintVerticalAlignmentBottom),
          @(MKUILayoutConstraintHorizontalAlignmentRight),
          ];
        __share__ = map;
    });
    return __share__;
}
+ (NSDictionary<NSArray<NSNumber *> *,NSNumber *> *)ConstraintParamRevertMap{
    static NSDictionary<NSArray<NSNumber *> *,NSNumber *> * __share__;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSDictionary<NSNumber *,NSArray<NSNumber *> *> *ConstraintParamMap = [self ConstraintParamMap];
        NSMutableDictionary<NSArray<NSNumber *> *,NSNumber *> *map = [[NSMutableDictionary alloc] initWithCapacity:ConstraintParamMap.count];
        for (NSNumber *key in ConstraintParamMap) {
            map[ConstraintParamMap[key]] = key;
        }
        __share__ = map;
    });
    return __share__;
}
+ (void)parseConstraintParam:(MKUIWaterFlowLayoutConstraintParam)param layoutDirection:(MKUILayoutConstraintDirection *)layoutDirection layoutVerticalAlignment:(MKUILayoutConstraintVerticalAlignment *)layoutVerticalAlignment layoutHorizontalAlignment:(MKUILayoutConstraintHorizontalAlignment *)layoutHorizontalAlignment{
    NSDictionary<NSNumber *,NSArray<NSNumber *> *> *ConstraintParamMap = [self.class ConstraintParamMap];
    NSArray<NSNumber *> *enums = ConstraintParamMap[@(param)];
    *layoutDirection = [enums[0] integerValue];
    *layoutVerticalAlignment = [enums[1] integerValue];
    *layoutHorizontalAlignment = [enums[2] integerValue];
}
+ (MKUIWaterFlowLayoutConstraintParam)constraintParamWithLayoutDirection:(MKUILayoutConstraintDirection)layoutDirection layoutVerticalAlignment:(MKUILayoutConstraintVerticalAlignment)layoutVerticalAlignment layoutHorizontalAlignment:(MKUILayoutConstraintHorizontalAlignment)layoutHorizontalAlignment{
    NSDictionary<NSArray<NSNumber *> *,NSNumber *> *ConstraintParamRevertMap = [self.class ConstraintParamRevertMap];
    MKUIWaterFlowLayoutConstraintParam param = (MKUIWaterFlowLayoutConstraintParam)[ConstraintParamRevertMap[@[@(layoutDirection),@(layoutVerticalAlignment),@(layoutHorizontalAlignment)]] integerValue];
    return param;
}
//////////////////////////////////////////////////////////////////////////////
- (id)initWithItems:(NSArray<id<MKUILayoutConstraintItemProtocol>> *)items constraintParam:(MKUIWaterFlowLayoutConstraintParam)param contentInsets:(UIEdgeInsets)contentInsets interitemSpacing:(CGFloat)interitemSpacing lineSpacing:(CGFloat)lineSpacing{
    if(self=[self init]){
        self.items = items;
        self.contentInsets = contentInsets;
        self.interitemSpacing = interitemSpacing;
        self.lineSpacing = lineSpacing;
        [self configWithConstraintParam:param];
    }
    return self;
}
- (void)setConstraintParam:(MKUIWaterFlowLayoutConstraintParam)constraintParam{
    [self configWithConstraintParam:constraintParam];
}
- (MKUIWaterFlowLayoutConstraintParam)constraintParam{
    MKUIWaterFlowLayoutConstraintParam param = [self.class constraintParamWithLayoutDirection:self.layoutDirection layoutVerticalAlignment:self.layoutVerticalAlignment layoutHorizontalAlignment:self.layoutHorizontalAlignment];
    return param;
}
- (void)configWithConstraintParam:(MKUIWaterFlowLayoutConstraintParam)param{
    MKUILayoutConstraintDirection layoutDirection;
    MKUILayoutConstraintVerticalAlignment layoutVerticalAlignment;
    MKUILayoutConstraintHorizontalAlignment layoutHorizontalAlignment;
    [self.class parseConstraintParam:param layoutDirection:&layoutDirection layoutVerticalAlignment:&layoutVerticalAlignment layoutHorizontalAlignment:&layoutHorizontalAlignment];
    self.layoutDirection = layoutDirection;
    self.layoutVerticalAlignment = layoutVerticalAlignment;
    self.layoutHorizontalAlignment = layoutHorizontalAlignment;
}
@end
